/*
	Copyright (C) 2010 2011 Rémi Thebault

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <QVariant>

#include <procycle/task.h>
#include <procycle/macrotask.h>
#include <procycle/cycle.h>

namespace PC {


	Task::Task(Cycle* cycle, MacroTask* parent)
	:	m_cycle(cycle)
	,	m_parent(parent)
	,	m_num(-1)
	,	m_name("")
	,	m_length(1)
	,	m_start(0)
	,	m_finish(0)
	,	m_lateStart(0)
	,	m_lateFinish(0)
	{
	}

	Task::Task(Task* other)
		:	m_cycle(other->cycle())
		,	m_parent(other->parent())
		,	m_num(other->num())
		,	m_name(other->name())
		,	m_length(other->length())
		,	m_start(other->start())
		,	m_finish(other->finish())
		,	m_lateStart(other->lateStart())
		,	m_lateFinish(other->lateFinish())
	{
		setObjectName(m_name);
	}

	Task::~Task() {
	}



	Task* Task::directCycleChildAncestor() {
		PC::MacroTask* currentParent = parent();
		PC::Task* currentChild = this;
		while (currentParent) {
			if (currentParent == static_cast<MacroTask*>(cycle())) {
				return currentChild;
			}
			currentChild = currentParent;
			currentParent = currentParent->parent();
		}
		return 0;
	}


	QString Task::tbsId() const {
		return makeTbsId(m_parent, pos());
	}


	int Task::pos() const {
		// TODO : implement from cycle
		return m_parent ? m_parent->posForTask(this) : 0;
	}


	void Task::preSchedule() {
		m_length_old = m_length;
		m_start_old = m_start;
		m_finish_old = m_finish;
		m_lateStart_old = m_lateStart;
		m_lateFinish_old = m_lateFinish;
	}


	void Task::postSchedule() {
		m_fTmps.clear();
		m_bTmps.clear();
		if (	m_length_old != m_length ||
				m_start_old != m_start ||
				m_finish_old != m_finish ||
				m_lateStart_old != m_lateStart ||
				m_lateFinish_old != m_lateFinish) {
			emit taskTimeChanged(this);
		}
	}

	int Task::minBTmp() {
		if (!m_bTmps.isEmpty()) {
			int min = m_bTmps.at(0);
			for(int i=1; i<m_bTmps.size(); i++) {
				if (m_bTmps.at(i) < min) {
					min = m_bTmps.at(i);
				}
			}
			return min;
		}
		return 0;
	}


	int Task::maxFTmp() {
		if (!m_fTmps.isEmpty()) {
			int max = m_fTmps.at(0);
			for(int i=1; i<m_fTmps.size(); i++) {
				if (m_fTmps.at(i) > max) {
					max = m_fTmps.at(i);
				}
			}
			return max;
		}
		return 0;
	}






	bool Task::canIndent() {
		return m_parent && pos() > 0;
	}

	bool Task::canUnindent() {
		return m_parent && m_parent->parent();
	}



	void
	Task::loadFromElement(const QDomElement& element) {
		XmlStorable::loadFromElement(element);
		m_name = element.attribute("name");
		setObjectName(m_name);
		QList<QDomElement> pl = directElementsByTagName(element, "property");
		foreach(QDomElement pe, pl) {
			QString name = pe.attribute("name");
			QString type = pe.attribute("type");
			if (!name.isEmpty() && !type.isEmpty()) {
				QByteArray array = name.toUtf8();
				const char* cname = array.constData();
				QString val = pe.text();
				if (type == "bool") {
					if (val == "true") {
						setProperty(cname, QVariant(true));
					}
					else if (val == "false") {
						setProperty(cname, QVariant(false));
					}
				}
				else if(type == "int") {
					if (!val.isEmpty()) {
						bool ok;
						int i = val.toInt(&ok);
						if (ok) {
							setProperty(cname, QVariant(i));
						}
					}
				}
				else if (type == "string") {
					setProperty(cname, QVariant(val));
				}
			}
		}
	}


	QDomElement
	Task::saveToElement(QDomDocument& doc) const {
		QDomElement element = XmlStorable::saveToElement(doc);
		element.setAttribute("name", m_name);
		foreach (QByteArray ba, dynamicPropertyNames()) {
			QDomElement pe = doc.createElement("property");
			pe.setAttribute("name", QString(ba.data()));
			QVariant pd = property(ba.data());
			switch (pd.type()) {
			case QVariant::Bool:
				pe.setAttribute("type", "bool");
				pe.appendChild(
					doc.createTextNode(
						(pd.toBool() ? "true": "false")
					)
				);
				break;
			case QVariant::Int:
				pe.setAttribute("type", "int");
				pe.appendChild(
					doc.createTextNode(
						QString::number(pd.toInt())
					)
				);
				break;
			case QVariant::String:
				pe.setAttribute("type", "string");
				pe.appendChild(
					doc.createTextNode(pd.toString())
				);
				break;
			}
			element.appendChild(pe);
		}

		return element;
	}

}
